#!/command/with-contenv bashio
# vim: ft=bash
# shellcheck shell=bash
# ==============================================================================
# Post-start initialization of MariaDB service
# ==============================================================================

function execute_without_error_messages() {
    local current_log_level="${__BASHIO_LOG_LEVELS[${__BASHIO_LOG_LEVEL}]}"
    bashio::log.level fatal
    local exit_code=0
    # shellcheck disable=SC2068
    $@ || exit_code=$?
    # shellcheck disable=SC2086
    bashio::log.level ${current_log_level}
    return ${exit_code}
}

# Wait until DB is running
while ! mysql -e "" 2> /dev/null; do
    sleep 1
done
bashio::log.info "MariaDB started"

# Delete service information, just in case the previous instance somehow did not cleanup
execute_without_error_messages bashio::services.delete "mysql" || true

bashio::log.info "Check data integrity and fix corruptions"
mysqlcheck --no-defaults --databases mysql --fix-db-names --fix-table-names || true
mysqlcheck --no-defaults --databases mysql --check --check-upgrade --auto-repair || true
mysqlcheck --no-defaults --all-databases --skip-database=mysql --fix-db-names --fix-table-names || true
mysqlcheck --no-defaults --all-databases --skip-database=mysql --check --check-upgrade --auto-repair || true

bashio::log.info "Ensuring internal database upgrades are performed"
mysql_upgrade --silent

# Set default secure values after initial setup
if bashio::var.true "${NEW_INSTALL}"; then
    # Secure the installation.
    mysql <<-EOSQL
        SET @@SESSION.SQL_LOG_BIN=0;
        DELETE FROM
            mysql.user
        WHERE
            user NOT IN ('mysql.sys', 'mariadb.sys', 'mysqlxsys', 'root', 'mysql', 'proxies_priv')
                OR host NOT IN ('localhost');
        DELETE FROM
            mysql.proxies_priv
        WHERE
            user NOT IN ('mysql.sys', 'mariadb.sys', 'mysqlxsys', 'root', 'mysql', 'proxies_priv')
                OR host NOT IN ('localhost');
        DROP DATABASE IF EXISTS test;
        FLUSH PRIVILEGES;
EOSQL
fi

# Init databases
bashio::log.info "Ensure databases exists"
for database in $(bashio::config "databases"); do
    bashio::log.info "Create database ${database}"
    mysql -e "CREATE DATABASE ${database};" 2> /dev/null || true
done

# Init logins
bashio::log.info "Ensure users exists and are updated"
for login in $(bashio::config "logins|keys"); do
    USERNAME=$(bashio::config "logins[${login}].username")
    PASSWORD=$(bashio::config "logins[${login}].password")

    if mysql -e "SET PASSWORD FOR '${USERNAME}'@'%' = PASSWORD('${PASSWORD}');" 2> /dev/null; then
        bashio::log.info "Update user ${USERNAME}"
    else
        bashio::log.info "Create user ${USERNAME}"
        mysql -e "CREATE USER '${USERNAME}'@'%' IDENTIFIED BY '${PASSWORD}';" 2> /dev/null || true
    fi
done

# Init rights
bashio::log.info "Init/Update rights"
for right in $(bashio::config "rights|keys"); do
    USERNAME=$(bashio::config "rights[${right}].username")
    DATABASE=$(bashio::config "rights[${right}].database")

    if bashio::config.exists "rights[${right}].privileges"; then
        PRIVILEGES=$(bashio::config "rights[${right}].privileges")
        bashio::log.info "Granting ${PRIVILEGES} to ${USERNAME} on ${DATABASE}"
        mysql -e "REVOKE ALL PRIVILEGES ON ${DATABASE}.* FROM '${USERNAME}'@'%';" || true
        mysql -e "GRANT ${PRIVILEGES} ON ${DATABASE}.* TO '${USERNAME}'@'%';" || true
    else
        bashio::log.info "Granting all privileges to ${USERNAME} on ${DATABASE}"
        mysql -e "GRANT ALL PRIVILEGES ON ${DATABASE}.* TO '${USERNAME}'@'%';" 2> /dev/null || true
    fi
done

# Generate service user
if ! bashio::fs.file_exists "/data/secret"; then
    pwgen 64 1 > /data/secret
fi
SECRET=$(</data/secret)
mysql -e "CREATE USER 'service'@'172.30.32.%' IDENTIFIED BY '${SECRET}';" 2> /dev/null || true
mysql -e "CREATE USER 'service'@'172.30.33.%' IDENTIFIED BY '${SECRET}';" 2> /dev/null || true
mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'service'@'172.30.32.%' WITH GRANT OPTION;" 2> /dev/null || true
mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'service'@'172.30.33.%' WITH GRANT OPTION;" 2> /dev/null || true

# Flush privileges
mysql -e "FLUSH PRIVILEGES;" 2> /dev/null || true

# Send service information to the Supervisor
PAYLOAD=$(\
    bashio::var.json \
        host "$(hostname)" \
        port "^3306" \
        username "service" \
        password "${SECRET}"
)
bashio::log.info "Sending service information to Home Assistant"
bashio::services.publish "mysql" "${PAYLOAD}"
